home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / msysjour / vol05 / 02 / checker3 / ckrdraw.c < prev    next >
Text File  |  1990-03-19  |  34KB  |  1,002 lines

  1. /*--------------------------------------------------------
  2.    CKRDRAW.C -- Ckd Board Drawing Functions, Version 0.30
  3.                 (c) 1990, Charles Petzold
  4.   --------------------------------------------------------*/
  5.  
  6. #define INCL_WIN
  7. #define INCL_GPI
  8. #include <os2.h>
  9. #include <stdlib.h>
  10. #include "checkers.h"
  11. #include "ckrdraw.h"
  12.  
  13.      /*----------------------------------------
  14.         Defines for board and piece dimensions
  15.        ----------------------------------------*/
  16.  
  17. #define BRD_HORZFRONT        500
  18. #define BRD_HORZBACK         350
  19. #define BRD_VERT             300
  20. #define BRD_EDGE              75
  21. #define BRD_HORZMARGIN       250
  22. #define BRD_FRONTMARGIN      250
  23. #define BRD_BACKMARGIN       250
  24. #define PIECE_XAXIS          (BRD_HORZBACK - 50)
  25. #define PIECE_YAXIS          (BRD_VERT - 50)
  26. #define PIECE_HEIGHT          50
  27.  
  28.      /*-------------------------------------
  29.         Global variables external to module
  30.        -------------------------------------*/
  31.  
  32. extern HAB hab ;
  33.  
  34.      /*-------------------------------------
  35.         Global variables internal to module
  36.        -------------------------------------*/
  37.  
  38.                // Background, board, and piece colors
  39.  
  40. static LONG clrBackground  = CLR_CYAN ;
  41. static LONG clrBlackSquare = CLR_DARKGREEN ;
  42. static LONG clrWhiteSquare = CLR_PALEGRAY ;
  43. static LONG clrBlackPiece  = CLR_RED ;
  44. static LONG clrWhitePiece  = CLR_WHITE ;
  45.  
  46.                // Text strings for saving colors to OS2.INI
  47.  
  48. static CHAR szApplication []    = "Checkers" ;
  49. static CHAR szClrBackground []  = "Background Color" ;
  50. static CHAR szClrBlackSquare [] = "Black Square Color" ;
  51. static CHAR szClrWhiteSquare [] = "White Square Color" ;
  52. static CHAR szClrBlackPiece []  = "Black Piece Color" ;
  53. static CHAR szClrWhitePiece []  = "White Piece Color" ;
  54.  
  55.                // Original viewport for adjusting board to window size
  56.  
  57. static RECTL rclOrigViewport ;
  58.  
  59.                // Bitmaps for drawing pieces
  60.  
  61. static HDC     hdcMemory, hdcMemory2 ;
  62. static HPS     hpsMemory, hpsMemory2 ;
  63. static HBITMAP ahbmPiece[2][2], ahbmMask[2], ahbmSave[2], ahbmMove[2] ;
  64. static SIZEL   sizlPiece[2], sizlMove[2] ;
  65.  
  66.      /*-------------------------------------------------------------
  67.         CkdQueryBoardDimensions: Obtains size of board with margins
  68.        -------------------------------------------------------------*/
  69.  
  70. static VOID CkdQueryBoardDimensions (SIZEL *psizlPage)
  71.      {
  72.      psizlPage->cx = 8 * BRD_HORZFRONT + 2 * BRD_HORZMARGIN ;
  73.      psizlPage->cy = 8 * BRD_VERT + BRD_FRONTMARGIN + BRD_BACKMARGIN ;
  74.      }
  75.  
  76.      /*-----------------------------------------------------------
  77.         CkdQuerySquareOrigin: Obtains lower left corner of square
  78.        -----------------------------------------------------------*/
  79.  
  80. static VOID CkdQuerySquareOrigin (SHORT x, SHORT y, POINTL *pptl)
  81.      {
  82.      pptl->x = BRD_HORZMARGIN + y * (BRD_HORZFRONT - BRD_HORZBACK) / 2 +
  83.                     x * (y * BRD_HORZBACK + (8 - y) * BRD_HORZFRONT) / 8 ;
  84.  
  85.      pptl->y = BRD_FRONTMARGIN + y * BRD_VERT ;
  86.      }
  87.  
  88.      /*-----------------------------------------------------
  89.         CkdQuerySquareCoords: Obtains coordinates of square
  90.        -----------------------------------------------------*/
  91.  
  92. static VOID CkdQuerySquareCoords (SHORT x, SHORT y, POINTL aptl[])
  93.      {
  94.      CkdQuerySquareOrigin (x,     y,     aptl + 0) ;
  95.      CkdQuerySquareOrigin (x + 1, y,     aptl + 1) ;
  96.      CkdQuerySquareOrigin (x + 1, y + 1, aptl + 2) ;
  97.      CkdQuerySquareOrigin (x,     y + 1, aptl + 3) ;
  98.      }
  99.      /*-----------------------------------------------
  100.         CkdDrawBoardSquare: Draws one square of board
  101.        -----------------------------------------------*/
  102.  
  103. static LONG CkdDrawBoardSquare (HPS hps, SHORT x, SHORT y)
  104.      {
  105.      AREABUNDLE abnd ;
  106.      LINEBUNDLE lbnd ;
  107.      LONG       lReturn ;
  108.      POINTL     aptl[4] ;
  109.  
  110.      GpiSavePS (hps) ;
  111.  
  112.      if (x < 0 || x >= 8 || y < 0 || y >= 8)
  113.           {
  114.           GpiSetColor (hps, clrBackground) ;
  115.           }
  116.      else
  117.           {
  118.           lbnd.lColor = CLR_BLACK ;
  119.           GpiSetAttrs (hps, PRIM_LINE, LBB_COLOR, 0L, &lbnd) ;
  120.  
  121.           abnd.lColor = (x + y) & 1 ? clrWhiteSquare : clrBlackSquare ;
  122.           GpiSetAttrs (hps, PRIM_AREA, LBB_COLOR, 0L, &abnd) ;
  123.           }
  124.  
  125.      GpiBeginArea (hps, BA_ALTERNATE | BA_BOUNDARY) ;
  126.  
  127.      CkdQuerySquareCoords (x, y, aptl) ;
  128.      GpiMove (hps, aptl + 3) ;
  129.      GpiPolyLine (hps, 4L, aptl) ;
  130.      lReturn = GpiEndArea (hps) ;
  131.  
  132.      GpiRestorePS (hps, -1L) ;
  133.  
  134.      return lReturn ;
  135.      }
  136.  
  137.      /*----------------------------------------------------
  138.         CkdDrawAllBoardSquares: Draws all squares of board
  139.        ----------------------------------------------------*/
  140.  
  141. static LONG CkdDrawAllBoardSquares (HPS hps)
  142.      {
  143.      SHORT x, y ;
  144.  
  145.      for (y = 0 ; y < 8 ; y++)
  146.           for (x = 0 ; x < 8 ; x++)
  147.                if (CkdDrawBoardSquare (hps, x, y) == GPI_HITS)
  148.                     return MAKELONG (x, y) ;
  149.  
  150.      return MAKELONG (-1, -1) ;
  151.      }
  152.  
  153.      /*----------------------------------------------------
  154.         CkdRenderPiece: Draws piece on bitmap in memory PS
  155.        ----------------------------------------------------*/
  156.  
  157. static VOID CkdRenderPiece (HPS hpsMemory, LONG lColorBack, LONG lColor,
  158.                             LONG lColorLine, SHORT sKing)
  159.      {
  160.      ARCPARAMS  arcp ;
  161.      AREABUNDLE abnd ;
  162.      LINEBUNDLE lbnd ;
  163.      POINTL     ptl, aptlArc[2] ;
  164.      SHORT      s ;
  165.  
  166.      GpiSavePS (hpsMemory) ;
  167.  
  168.                // Draw background of bitmap
  169.  
  170.      GpiSetColor (hpsMemory, lColorBack) ;
  171.  
  172.      ptl.x = 0 ;
  173.      ptl.y = 0 ;
  174.      GpiMove (hpsMemory, &ptl) ;
  175.  
  176.      ptl.x = PIECE_XAXIS ;
  177.      ptl.y = PIECE_YAXIS + (sKing + 1) * PIECE_HEIGHT ;
  178.      GpiBox (hpsMemory, DRO_FILL, &ptl, 0L, 0L) ;
  179.  
  180.                // Set colors for areas and outlines
  181.  
  182.      abnd.lColor = lColor ;
  183.      GpiSetAttrs (hpsMemory, PRIM_AREA, ABB_COLOR, 0L, &abnd) ;
  184.  
  185.      lbnd.lColor = lColorLine ;
  186.      GpiSetAttrs (hpsMemory, PRIM_LINE, LBB_COLOR, 0L, &lbnd) ;
  187.  
  188.                // Set arc parameters
  189.  
  190.      arcp.lP = PIECE_XAXIS / 2 ;
  191.      arcp.lQ = PIECE_YAXIS / 2 ;
  192.      arcp.lR = 0 ;
  193.      arcp.lS = 0 ;
  194.      GpiSetArcParams (hpsMemory, &arcp) ;
  195.  
  196.                // draw the piece
  197.  
  198.      for (s = 0 ; s <= sKing ; s++)
  199.           {
  200.           GpiBeginArea (hpsMemory, BA_ALTERNATE | BA_BOUNDARY) ;
  201.  
  202.           ptl.x = 0 ;
  203.           ptl.y = PIECE_YAXIS / 2 + (s + 1) * PIECE_HEIGHT ;
  204.           GpiMove (hpsMemory, &ptl) ;
  205.  
  206.           ptl.y -= PIECE_HEIGHT ;
  207.           GpiLine (hpsMemory, &ptl) ;
  208.  
  209.           aptlArc[0].x = PIECE_XAXIS / 2 ;
  210.           aptlArc[0].y = s * PIECE_HEIGHT ;
  211.           aptlArc[1].x = PIECE_XAXIS ;
  212.           aptlArc[1].y = PIECE_YAXIS / 2 + s * PIECE_HEIGHT ;
  213.  
  214.           GpiPointArc (hpsMemory, aptlArc) ;
  215.  
  216.           ptl.x = PIECE_XAXIS ;
  217.           ptl.y = PIECE_YAXIS / 2 + (s + 1) * PIECE_HEIGHT ;
  218.           GpiLine (hpsMemory, &ptl) ;
  219.  
  220.           GpiEndArea (hpsMemory) ;
  221.           }
  222.  
  223.      ptl.x = PIECE_XAXIS / 2 ;
  224.      ptl.y = PIECE_YAXIS / 2 + (sKing ? 2 : 1) * PIECE_HEIGHT ;
  225.  
  226.      GpiMove (hpsMemory, &ptl) ;
  227.      GpiFullArc (hpsMemory, DRO_OUTLINEFILL, MAKEFIXED (1,0)) ;
  228.  
  229.      GpiRestorePS (hpsMemory, -1L) ;
  230.      }
  231.  
  232.      /*------------------------------------------------------
  233.         CkdQuerySquareCenter: Obtains center of board square
  234.        ------------------------------------------------------*/
  235.  
  236. static VOID CkdQuerySquareCenter (SHORT x, SHORT y, POINTL *pptlCenter)
  237.      {
  238.      POINTL aptl[4] ;
  239.  
  240.      CkdQuerySquareCoords (x, y, aptl) ;
  241.  
  242.      pptlCenter->x = (aptl[0].x + aptl[1].x + aptl[2].x + aptl[3].x) / 4 ;
  243.      pptlCenter->y = (aptl[1].y + aptl[2].y) / 2 ;
  244.      }
  245.  
  246.      /*---------------------------------------------------------------------
  247.         CkdPieceOriginFromCenter: Converts center of square to piece origin
  248.        ---------------------------------------------------------------------*/
  249.  
  250. static VOID CkdPieceOriginFromCenter (POINTL *pptl)
  251.      {
  252.      pptl->x -= PIECE_XAXIS / 2 ;
  253.      pptl->y -= PIECE_YAXIS / 2 ;
  254.      }
  255.  
  256.      /*-----------------------------------------------------------------
  257.         CkdPieceOriginFromCenter: Same as above, but device coordinates
  258.        -----------------------------------------------------------------*/
  259.  
  260. static VOID CkdPieceOriginFromCenterDevice (POINTL *pptlOrg, POINTL *pptlCntr)
  261.      {
  262.      pptlOrg->x = pptlCntr->x - sizlPiece[0].cx / 2 ;
  263.      pptlOrg->y = pptlCntr->y - sizlPiece[0].cy / 2 ;
  264.      }
  265.  
  266.      /*----------------------------------------------------------------
  267.         CkdQuerySquarePieceOrigin: Obtains origin of piece on a square
  268.        ----------------------------------------------------------------*/
  269.  
  270. static VOID CkdQuerySquarePieceOrigin (SHORT x, SHORT y, POINTL *pptlOrigin)
  271.      {
  272.      CkdQuerySquareCenter (x, y, pptlOrigin) ;
  273.      CkdPieceOriginFromCenter (pptlOrigin) ;
  274.      }
  275.  
  276.      /*-------------------------------------------------------------
  277.         CkdShowPiece: Draws a piece on the screen at specific point
  278.        -------------------------------------------------------------*/
  279.  
  280. static VOID CkdShowPiece (HPS hps, POINTL *pptlOrg, SHORT sColor, SHORT sKing)
  281.      {
  282.      POINTL aptl[3] ;
  283.  
  284.                // Write out mask with bitwise AND
  285.  
  286.      aptl[0]   = *pptlOrg ;
  287.      aptl[1].x = pptlOrg->x + sizlPiece[sKing].cx ;
  288.      aptl[1].y = pptlOrg->y + sizlPiece[sKing].cy ;
  289.      aptl[2].x = 0 ;
  290.      aptl[2].y = 0 ;
  291.  
  292.      GpiSetBitmap (hpsMemory, ahbmMask[sKing]) ;
  293.      GpiBitBlt    (hps, hpsMemory, 3L, aptl, ROP_SRCAND, BBO_IGNORE) ;
  294.  
  295.                // Write out piece with bitwise OR
  296.  
  297.      aptl[0]   = *pptlOrg ;
  298.      aptl[1].x = pptlOrg->x + sizlPiece[sKing].cx ;
  299.      aptl[1].y = pptlOrg->y + sizlPiece[sKing].cy ;
  300.      aptl[2].x = 0 ;
  301.      aptl[2].y = 0 ;
  302.  
  303.      GpiSetBitmap (hpsMemory, ahbmPiece[sColor][sKing]) ;
  304.      GpiBitBlt    (hps, hpsMemory, 3L, aptl, ROP_SRCPAINT, BBO_IGNORE) ;
  305.  
  306.      GpiSetBitmap (hpsMemory, NULL) ;
  307.      }
  308.  
  309.      /*---------------------------------------------------------------------
  310.         CkdDrawOnePiece: Draws a piece on the board at specific coordinates
  311.        ---------------------------------------------------------------------*/
  312.  
  313. static VOID CkdDrawOnePiece (HPS hps, SHORT x, SHORT y,
  314.                              BOARD *pbrd, SHORT sBottom)
  315.      {
  316.      POINTL ptlOrigin ;
  317.      SHORT  i, sKing ;
  318.  
  319.      i = CkdConvertCoordsToIndex (x, y, sBottom) ;
  320.  
  321.      if (i == -1)
  322.           return ;
  323.  
  324.      CkdQuerySquarePieceOrigin (x, y, &ptlOrigin) ;
  325.      GpiConvert (hps, CVTC_PAGE, CVTC_DEVICE, 1L, &ptlOrigin) ;
  326.  
  327.      sKing = pbrd->ulKing & 1L << i ? 1 : 0 ;
  328.  
  329.      if (pbrd->ulBlack & 1L << i)
  330.           CkdShowPiece (hps, &ptlOrigin, BLACK, sKing) ;
  331.  
  332.      if (pbrd->ulWhite & 1L << i)
  333.           CkdShowPiece (hps, &ptlOrigin, WHITE, sKing) ;
  334.      }
  335.  
  336.      /*----------------------------------------------------
  337.         ColorDlgProc: Dialog procedure for changing colors
  338.        ----------------------------------------------------*/
  339.  
  340. MRESULT EXPENTRY ColorDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  341.      {
  342.      static LONG  *pclr ;
  343.      static SHORT sColor ;
  344.      CHAR         *pchHeading ;
  345.  
  346.      switch (msg)
  347.           {
  348.           case WM_INITDLG:
  349.                switch (* (PSHORT) PVOIDFROMMP (mp2))
  350.                     {
  351.                     case IDM_COLOR_BACKGROUND:
  352.                          pchHeading = "Window Background Color" ;
  353.                          pclr = &clrBackground ;
  354.                          break ;
  355.  
  356.                     case IDM_COLOR_BLACK_SQUARE:
  357.                          pchHeading = "Black Square Color" ;
  358.                          pclr = &clrBlackSquare ;
  359.                          break ;
  360.  
  361.                     case IDM_COLOR_WHITE_SQUARE:
  362.                          pchHeading = "White Square Color" ;
  363.                          pclr = &clrWhiteSquare ;
  364.                          break ;
  365.  
  366.                     case IDM_COLOR_BLACK_PIECE:
  367.                          pchHeading = "Black Piece Color" ;
  368.                          pclr = &clrBlackPiece ;
  369.                          break ;
  370.  
  371.                     case IDM_COLOR_WHITE_PIECE:
  372.                          pchHeading = "White Piece Color" ;
  373.                          pclr = &clrWhitePiece ;
  374.                          break ;
  375.                     }
  376.                WinSetDlgItemText (hwnd, IDD_HEADING, pchHeading) ;
  377.  
  378.                sColor = (SHORT) *pclr ;
  379.  
  380.                WinSendDlgItemMsg (hwnd, IDD_COLOR + sColor, BM_SETCHECK,
  381.                                   MPFROM2SHORT (TRUE, 0), NULL) ;
  382.  
  383.                WinSetFocus (HWND_DESKTOP,
  384.                             WinWindowFromID (hwnd, IDD_COLOR + sColor)) ;
  385.                return 1 ;
  386.  
  387.           case WM_CONTROL:
  388.                WinSendDlgItemMsg (hwnd, IDD_COLOR + sColor, BM_SETCHECK,
  389.                                   MPFROM2SHORT (FALSE, 0), NULL) ;
  390.  
  391.                sColor = SHORT1FROMMP (mp1) - IDD_COLOR ;
  392.  
  393.                WinSendDlgItemMsg (hwnd, IDD_COLOR + sColor, BM_SETCHECK,
  394.                                   MPFROM2SHORT (TRUE, 0), NULL) ;
  395.                return 0 ;
  396.  
  397.           case WM_COMMAND:
  398.                switch (COMMANDMSG(&msg)->cmd)
  399.                     {
  400.                     case DID_OK:
  401.                          *pclr = (LONG) sColor ;
  402.                          WinDismissDlg (hwnd, TRUE) ;
  403.                          return 0 ;
  404.  
  405.                     case DID_CANCEL:
  406.                          WinDismissDlg (hwnd, FALSE) ;
  407.                          return 0 ;
  408.                     }
  409.                break ;
  410.           }
  411.      return WinDefDlgProc (hwnd, msg, mp1, mp2) ;
  412.      }
  413.  
  414.      /*-------------------------------------------------
  415.         CkdCreatePS: Create PS for checker board window
  416.        -------------------------------------------------*/
  417.  
  418. HPS CkdCreatePS (HWND hwnd)
  419.      {
  420.      HDC    hdc ;
  421.      HPS    hps ;
  422.      SIZEL  sizlPage ;
  423.      USHORT sDataSize ;
  424.  
  425.      CkdQueryBoardDimensions (&sizlPage) ;
  426.  
  427.                // Create PS and save original viewport
  428.  
  429.      hdc = WinOpenWindowDC (hwnd) ;
  430.      hps = GpiCreatePS (hab, hdc, &sizlPage,
  431.                         PU_ARBITRARY | GPIF_DEFAULT |
  432.                         GPIT_MICRO   | GPIA_ASSOC) ;
  433.  
  434.      GpiQueryPageViewport (hps, &rclOrigViewport) ;
  435.  
  436.                // Create memory DC's and PS's
  437.  
  438.      hdcMemory  = DevOpenDC (hab, OD_MEMORY, "*", 0L, NULL, NULL) ;
  439.      hpsMemory  = GpiCreatePS (hab, hdcMemory, &sizlPage,
  440.                                PU_ARBITRARY | GPIF_DEFAULT |
  441.                                GPIT_MICRO   | GPIA_ASSOC) ;
  442.  
  443.      hdcMemory2 = DevOpenDC (hab, OD_MEMORY, "*", 0L, NULL, NULL) ;
  444.      hpsMemory2 = GpiCreatePS (hab, hdcMemory2, &sizlPage,
  445.                                PU_ARBITRARY | GPIF_DEFAULT |
  446.                                GPIT_MICRO   | GPIA_ASSOC) ;
  447.  
  448.                // Get colors from OS2.INI
  449.  
  450.      sDataSize = sizeof (LONG) ;
  451.      WinQueryProfileData (hab, szApplication, szClrBackground,
  452.                           &clrBackground, &sDataSize) ;
  453.  
  454.      sDataSize = sizeof (LONG) ;
  455.      WinQueryProfileData (hab, szApplication, szClrBlackSquare,
  456.                           &clrBlackSquare, &sDataSize) ;
  457.  
  458.      sDataSize = sizeof (LONG) ;
  459.      WinQueryProfileData (hab, szApplication, szClrWhiteSquare,
  460.                           &clrWhiteSquare, &sDataSize) ;
  461.  
  462.      sDataSize = sizeof (LONG) ;
  463.      WinQueryProfileData (hab, szApplication, szClrBlackPiece,
  464.                           &clrBlackPiece, &sDataSize) ;
  465.  
  466.      sDataSize = sizeof (LONG) ;
  467.      WinQueryProfileData (hab, szApplication, szClrWhitePiece,
  468.                           &clrWhitePiece, &sDataSize) ;
  469.      return hps ;
  470.      }
  471.  
  472.      /*-------------------------------------------------------
  473.         CkdResizePS: Change page viewport for new window size
  474.        -------------------------------------------------------*/
  475.  
  476. VOID CkdResizePS (HPS hps, HWND hwnd)
  477.      {
  478.      LONG  lScale ;
  479.      RECTL rclWindow, rclViewport ;
  480.  
  481.      WinQueryWindowRect (hwnd, &rclWindow) ;
  482.  
  483.                // Calculate scaling factor
  484.  
  485.      lScale = min (65536L * rclWindow.xRight / rclOrigViewport.xRight,
  486.                    65536L * rclWindow.yTop   / rclOrigViewport.yTop) ;
  487.  
  488.                // Adjust page viewport of memory PS
  489.  
  490.      rclViewport.xLeft   = 0 ;
  491.      rclViewport.yBottom = 0 ;
  492.      rclViewport.xRight  = lScale * rclOrigViewport.xRight / 65536L ;
  493.      rclViewport.yTop    = lScale * rclOrigViewport.yTop   / 65536L ;
  494.  
  495.      rclViewport.xLeft   = (rclWindow.xRight - rclViewport.xRight) / 2 ;
  496.      rclViewport.yBottom = (rclWindow.yTop   - rclViewport.yTop)   / 2 ;
  497.      rclViewport.xRight += rclViewport.xLeft ;
  498.      rclViewport.yTop   += rclViewport.yBottom ;
  499.  
  500.      GpiSetPageViewport (hps, &rclViewport) ;
  501.  
  502.                // Similarly for memory PS's
  503.  
  504.      rclViewport.xRight -= rclViewport.xLeft ;
  505.      rclViewport.yTop   -= rclViewport.yBottom ;
  506.      rclViewport.xLeft   = 0 ;
  507.      rclViewport.yBottom = 0 ;
  508.  
  509.      GpiSetPageViewport (hpsMemory,  &rclViewport) ;
  510.      GpiSetPageViewport (hpsMemory2, &rclViewport) ;
  511.      }
  512.  
  513.      /*---------------------------------------------------
  514.         CkdDestroyPS: Destroy PS for checker board window
  515.        ---------------------------------------------------*/
  516.  
  517. BOOL CkdDestroyPS (HPS hps)
  518.      {
  519.                // Save colors in OS2.INI
  520.  
  521.      WinWriteProfileData (hab, szApplication, szClrBackground,
  522.                           &clrBackground, sizeof (LONG)) ;
  523.  
  524.      WinWriteProfileData (hab, szApplication, szClrBlackSquare,
  525.                           &clrBlackSquare, sizeof (LONG)) ;
  526.  
  527.      WinWriteProfileData (hab, szApplication, szClrWhiteSquare,
  528.                           &clrWhiteSquare, sizeof (LONG)) ;
  529.  
  530.      WinWriteProfileData (hab, szApplication, szClrBlackPiece,
  531.                           &clrBlackPiece, sizeof (LONG)) ;
  532.  
  533.      WinWriteProfileData (hab, szApplication, szClrWhitePiece,
  534.                           &clrWhitePiece, sizeof (LONG)) ;
  535.  
  536.                // Destroy memory PS's and close DC's
  537.  
  538.      GpiDestroyPS (hpsMemory) ;
  539.      GpiDestroyPS (hpsMemory2) ;
  540.      DevCloseDC (hdcMemory) ;
  541.      DevCloseDC (hdcMemory2) ;
  542.  
  543.                // Destroy screen PS
  544.  
  545.      return GpiDestroyPS (hps) ;
  546.      }
  547.  
  548.      /*-----------------------------------------------------------
  549.         CkdSetStandardColors: Sets colors to tournament standards
  550.        -----------------------------------------------------------*/
  551.  
  552. VOID CkdSetStandardColors (VOID)
  553.      {
  554.      clrBackground  = CLR_CYAN ;
  555.      clrBlackSquare = CLR_DARKGREEN ;
  556.      clrWhiteSquare = CLR_PALEGRAY ;
  557.      clrBlackPiece  = CLR_RED ;
  558.      clrWhitePiece  = CLR_WHITE ;
  559.      }
  560.  
  561.      /*------------------------------------------------------------
  562.         CkdCreatePieces: Creates bitmaps to use for drawing pieces
  563.        ------------------------------------------------------------*/
  564.  
  565. VOID CkdCreatePieces (HPS hps)
  566.      {
  567.      BITMAPINFOHEADER bmp ;
  568.      LONG             alBitmapFormat[2] ;
  569.      SHORT            sColor, sKing ;
  570.  
  571.                // Get bitmap format of video display
  572.  
  573.      GpiQueryDeviceBitmapFormats (hps, 2L, alBitmapFormat) ;
  574.  
  575.                // Loop through possible color and size combinations
  576.  
  577.      for (sKing = 0 ; sKing < 2 ; sKing++)
  578.           {
  579.                     // Determine pixel dimensions of bitmaps
  580.  
  581.           sizlPiece[sKing].cx = PIECE_XAXIS ;
  582.           sizlPiece[sKing].cy = PIECE_YAXIS + (sKing + 1) * PIECE_HEIGHT ;
  583.  
  584.           GpiConvert (hpsMemory, CVTC_PAGE, CVTC_DEVICE, 1L,
  585.                       (PPOINTL) &sizlPiece[sKing]) ;
  586.  
  587.           sizlPiece[sKing].cx ++ ;
  588.           sizlPiece[sKing].cy ++ ;
  589.           sizlMove[sKing].cx = 2 * sizlPiece[sKing].cx ;
  590.           sizlMove[sKing].cy = 2 * sizlPiece[sKing].cy ;
  591.  
  592.                     // Set up BITMAPINFOHEADER structure
  593.  
  594.           bmp.cbFix     = sizeof bmp ;
  595.           bmp.cx        = (SHORT) sizlPiece[sKing].cx ;
  596.           bmp.cy        = (SHORT) sizlPiece[sKing].cy ;
  597.           bmp.cPlanes   = (SHORT) alBitmapFormat[0] ;
  598.           bmp.cBitCount = (SHORT) alBitmapFormat[1] ;
  599.  
  600.                     // Create ahbmPiece bitmaps
  601.  
  602.           for (sColor = BLACK ; sColor <= WHITE ; sColor++)
  603.                {
  604.                ahbmPiece[sColor][sKing] =
  605.                          GpiCreateBitmap (hps, &bmp, 0L, 0L, NULL) ;
  606.  
  607.                GpiSetBitmap (hpsMemory, ahbmPiece[sColor][sKing]) ;
  608.                CkdRenderPiece (hpsMemory, CLR_FALSE,
  609.                                sColor ? clrWhitePiece : clrBlackPiece,
  610.                                CLR_BLACK, sKing) ;
  611.                }
  612.  
  613.                     // Create ahbmMask bitmaps
  614.  
  615.           ahbmMask[sKing] = GpiCreateBitmap (hps, &bmp, 0L, 0L, NULL) ;
  616.           GpiSetBitmap (hpsMemory, ahbmMask[sKing]) ;
  617.           CkdRenderPiece (hpsMemory, CLR_TRUE, CLR_FALSE, CLR_FALSE, sKing) ;
  618.  
  619.                     // Create ahbmSave bitmaps
  620.  
  621.           ahbmSave[sKing] = GpiCreateBitmap (hps, &bmp, 0L, 0L, NULL) ;
  622.  
  623.                     // Create ahbmMove bitmaps
  624.  
  625.           bmp.cbFix     = sizeof bmp ;
  626.           bmp.cx        = (SHORT) sizlMove[sKing].cx ;
  627.           bmp.cy        = (SHORT) sizlMove[sKing].cy ;
  628.           bmp.cPlanes   = (SHORT) alBitmapFormat[0] ;
  629.           bmp.cBitCount = (SHORT) alBitmapFormat[1] ;
  630.  
  631.           ahbmMove[sKing] = GpiCreateBitmap (hps, &bmp, 0L, 0L, NULL) ;
  632.           }
  633.  
  634.      GpiSetBitmap (hpsMemory, NULL) ;
  635.      }
  636.  
  637.      /*---------------------------------------------------
  638.         CkdDestroyPieces: Destroy bitmaps used for pieces
  639.        ---------------------------------------------------*/
  640.  
  641. VOID CkdDestroyPieces (VOID)
  642.      {
  643.      SHORT sColor, sKing ;
  644.  
  645.      for (sKing = 0 ; sKing < 2 ; sKing++)
  646.           {
  647.           for (sColor = BLACK ; sColor <= WHITE ; sColor++)
  648.                if (ahbmPiece[sColor][sKing] != NULL)
  649.                     GpiDeleteBitmap (ahbmPiece[sColor][sKing]) ;
  650.  
  651.           if (ahbmMask[sKing] != NULL)
  652.                GpiDeleteBitmap (ahbmMask[sKing]) ;
  653.  
  654.           if (ahbmSave[sKing] != NULL)
  655.                GpiDeleteBitmap (ahbmSave[sKing]) ;
  656.  
  657.           if (ahbmMove[sKing] != NULL)
  658.                GpiDeleteBitmap (ahbmMove[sKing]) ;
  659.           }
  660.      }
  661.  
  662.      /*--------------------------------------------------------------------
  663.         CkdDrawWindowBackground: Fills entire window with background color
  664.        --------------------------------------------------------------------*/
  665.  
  666. VOID CkdDrawWindowBackground (HPS hps, HWND hwnd)
  667.      {
  668.      RECTL rcl ;
  669.  
  670.      WinQueryWindowRect (hwnd, &rcl) ;
  671.      WinFillRect (hps, &rcl, clrBackground) ;
  672.      }
  673.  
  674.      /*-----------------------------------------------------------
  675.         CkdDrawWholeBoard: Draws the board squares and front edge
  676.        -----------------------------------------------------------*/
  677.  
  678. VOID CkdDrawWholeBoard (HPS hps)
  679.      {
  680.      AREABUNDLE abnd ;
  681.      LINEBUNDLE lbnd ;
  682.      SHORT      x ;
  683.      POINTL     aptl[4] ;
  684.  
  685.      CkdDrawAllBoardSquares (hps) ;
  686.  
  687.      GpiSavePS (hps) ;
  688.  
  689.      lbnd.lColor = CLR_BLACK ;
  690.      GpiSetAttrs (hps, PRIM_LINE, LBB_COLOR, 0L, &lbnd) ;
  691.  
  692.      for (x = 0 ; x < 8 ; x++)
  693.           {
  694.           CkdQuerySquareCoords (x, 0, aptl) ;
  695.  
  696.           aptl[2].x = aptl[1].x ;
  697.           aptl[2].y = aptl[1].y - BRD_EDGE ;
  698.  
  699.           aptl[3].x = aptl[0].x ;
  700.           aptl[3].y = aptl[0].y - BRD_EDGE ;
  701.  
  702.           abnd.lColor = x & 1 ? clrWhiteSquare : clrBlackSquare ;
  703.           GpiSetAttrs (hps, PRIM_AREA, LBB_COLOR, 0L, &abnd) ;
  704.  
  705.           GpiBeginArea (hps, BA_ALTERNATE | BA_BOUNDARY) ;
  706.  
  707.           GpiMove (hps, aptl + 3) ;
  708.           GpiPolyLine (hps, 4L, aptl) ;
  709.  
  710.           GpiEndArea (hps) ;
  711.           }
  712.  
  713.      GpiRestorePS (hps, -1L) ;
  714.      }
  715.  
  716.      /*-----------------------------------------------------
  717.         CkdDrawAllPieces: Draws all the pieces on the board
  718.        -----------------------------------------------------*/
  719.  
  720. VOID CkdDrawAllPieces (HPS hps, BOARD *pbrd, SHORT sBottom)
  721.      {
  722.      SHORT x, y ;
  723.  
  724.      for (y = 0 ; y < 8 ; y++)
  725.           for (x = 0 ; x < 8 ; x++)
  726.                CkdDrawOnePiece (hps, x, y, pbrd, sBottom) ;
  727.      }
  728.  
  729.      /*---------------------------------------------------------------------
  730.         CkdErasePiece: Erases piece from board by drawing the board squares
  731.        ---------------------------------------------------------------------*/
  732.  
  733. VOID CkdErasePiece (HPS hps, SHORT x, SHORT y)
  734.      {
  735.      CkdDrawBoardSquare (hps, x, y + 1) ;
  736.      CkdDrawBoardSquare (hps, x, y) ;
  737.      }
  738.  
  739.      /*---------------------------------------------------------------
  740.         CkdQueryHitCoords: Obtains coords from mouse pointer position
  741.        ---------------------------------------------------------------*/
  742.  
  743. VOID CkdQueryHitCoords (HPS hps, POINTL ptlMouse, SHORT *px, SHORT *py)
  744.      {
  745.      LONG  lCoords ;
  746.      SIZEL sizlAperture ;
  747.  
  748.      sizlAperture.cx = 1 ;
  749.      sizlAperture.cy = 1 ;
  750.      GpiSetPickApertureSize (hps, PICKAP_REC, &sizlAperture) ;
  751.  
  752.      GpiConvert (hps, CVTC_DEVICE, CVTC_PAGE, 1L, &ptlMouse) ;
  753.      GpiSetPickAperturePosition (hps, &ptlMouse) ;
  754.  
  755.      GpiSetDrawControl (hps, DCTL_DISPLAY,   DCTL_OFF) ;
  756.      GpiSetDrawControl (hps, DCTL_CORRELATE, DCTL_ON) ;
  757.  
  758.      lCoords = CkdDrawAllBoardSquares (hps) ;
  759.  
  760.      GpiSetDrawControl (hps, DCTL_DISPLAY,   DCTL_ON) ;
  761.      GpiSetDrawControl (hps, DCTL_CORRELATE, DCTL_OFF) ;
  762.  
  763.      *px = LOUSHORT (lCoords) ;
  764.      *py = HIUSHORT (lCoords) ;
  765.      }
  766.  
  767.      /*-----------------------------------------------------------------------
  768.         CkdConvertCoordsToIndex: Obtains index (0-31) from square coordinates
  769.        -----------------------------------------------------------------------*/
  770.  
  771. SHORT CkdConvertCoordsToIndex (SHORT x, SHORT y, SHORT sBottom)
  772.      {
  773.      if (x < 0 || x > 7 || y < 0 || y > 7)
  774.           return -1 ;
  775.  
  776.      if ((x - (y & 1)) & 1)
  777.           return -1 ;
  778.  
  779.      if (sBottom == WHITE)
  780.           {
  781.           x = 7 - x ;
  782.           y = 7 - y ;
  783.           }
  784.  
  785.      return 3 ^ (4 * y + (x - (y & 1)) / 2) ;
  786.      }
  787.  
  788.      /*-----------------------------------------------------------------------
  789.         CkdConvertIndexToCoords: Obtains square coordinates from index (0-31)
  790.        -----------------------------------------------------------------------*/
  791.  
  792. VOID CkdConvertIndexToCoords (SHORT i, SHORT *px, SHORT *py, SHORT sBottom)
  793.      {
  794.      if (i <= 0 || i >= 32)
  795.           {
  796.           *px = -1 ;
  797.           *py = -1 ;
  798.           }
  799.  
  800.      *py = i / 4 ;
  801.      *px = 2 * ((i ^ 3) % 4) + (*py & 1) ;
  802.  
  803.      if (sBottom == WHITE)
  804.           {
  805.           *px = 7 - *px ;
  806.           *py = 7 - *py ;
  807.           }
  808.      }
  809.  
  810.      /*----------------------------------------------------
  811.         CkdDragSave: Saves screen area when dragging piece
  812.        ----------------------------------------------------*/
  813.  
  814. VOID CkdDragSave (HPS hps, POINTL *pptlMouse, SHORT sKing)
  815.      {
  816.      POINTL ptlOrigin, aptl[3] ;
  817.  
  818.      CkdPieceOriginFromCenterDevice (&ptlOrigin, pptlMouse) ;
  819.  
  820.      aptl[0].x = 0 ;
  821.      aptl[0].y = 0 ;
  822.      aptl[1].x = sizlPiece[sKing].cx ;
  823.      aptl[1].y = sizlPiece[sKing].cy ;
  824.      aptl[2]   = ptlOrigin ;
  825.  
  826.      GpiSetBitmap (hpsMemory, ahbmSave[sKing]) ;
  827.      GpiBitBlt    (hpsMemory, hps, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE) ;
  828.      GpiSetBitmap (hpsMemory, NULL) ;
  829.      }
  830.  
  831.      /*----------------------------------------------------------
  832.         CkdDragRestore: Restores screen area when dragging piece
  833.        ----------------------------------------------------------*/
  834.  
  835. VOID CkdDragRestore (HPS hps, POINTL *pptlMouse, SHORT sKing)
  836.      {
  837.      POINTL ptlOrigin, aptl[3] ;
  838.  
  839.      CkdPieceOriginFromCenterDevice (&ptlOrigin, pptlMouse) ;
  840.  
  841.      aptl[0]   = ptlOrigin ;
  842.      aptl[1].x = ptlOrigin.x + sizlPiece[sKing].cx ;
  843.      aptl[1].y = ptlOrigin.y + sizlPiece[sKing].cy ;
  844.      aptl[2].x = 0 ;
  845.      aptl[2].y = 0 ;
  846.  
  847.      GpiSetBitmap (hpsMemory, ahbmSave[sKing]) ;
  848.      GpiBitBlt    (hps, hpsMemory, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE) ;
  849.      GpiSetBitmap (hpsMemory, NULL) ;
  850.      }
  851.  
  852.      /*-------------------------------------------------------------
  853.         CkdDragShow: Shows piece in new position when being dragged
  854.        -------------------------------------------------------------*/
  855.  
  856. VOID CkdDragShow (HPS hps, POINTL *pptlMouse, SHORT sColor, SHORT sKing)
  857.      {
  858.      POINTL ptlOrigin, aptl[3] ;
  859.  
  860.      CkdPieceOriginFromCenterDevice (&ptlOrigin, pptlMouse) ;
  861.  
  862.                // Write out mask with bitwise AND
  863.  
  864.      aptl[0]   = ptlOrigin ;
  865.      aptl[1].x = ptlOrigin.x + sizlPiece[sKing].cx ;
  866.      aptl[1].y = ptlOrigin.y + sizlPiece[sKing].cy ;
  867.      aptl[2].x = 0 ;
  868.      aptl[2].y = 0 ;
  869.  
  870.      GpiSetBitmap (hpsMemory, ahbmMask[sKing]) ;
  871.      GpiBitBlt    (hps, hpsMemory, 3L, aptl, ROP_SRCAND, BBO_IGNORE) ;
  872.  
  873.                // Write out piece with bitwise OR
  874.  
  875.      aptl[0]   = ptlOrigin ;
  876.      aptl[1].x = ptlOrigin.x + sizlPiece[sKing].cx ;
  877.      aptl[1].y = ptlOrigin.y + sizlPiece[sKing].cy ;
  878.      aptl[2].x = 0 ;
  879.      aptl[2].y = 0 ;
  880.  
  881.      GpiSetBitmap (hpsMemory, ahbmPiece[sColor][sKing]) ;
  882.      GpiBitBlt    (hps, hpsMemory, 3L, aptl, ROP_SRCPAINT, BBO_IGNORE) ;
  883.      GpiSetBitmap (hpsMemory, NULL) ;
  884.      }
  885.  
  886.      /*-------------------------------------------------------------
  887.         CkdDragMove: Moves piece from one part of screen to another
  888.        -------------------------------------------------------------*/
  889.  
  890. VOID CkdDragMove (HPS hps, POINTL *pptlFrom, POINTL *pptlTo,
  891.                            SHORT sColor, SHORT sKing)
  892.      {
  893.      POINTL ptlCenter, ptlOrigin, aptl[3], ptlFrom, ptlTo ;
  894.  
  895.      if ((labs (pptlFrom->x - pptlTo->x) > sizlPiece[sKing].cx) ||
  896.          (labs (pptlFrom->y - pptlTo->y) > sizlPiece[sKing].cy))
  897.           {
  898.           CkdDragRestore (hps, pptlFrom, sKing) ;
  899.           CkdDragSave    (hps, pptlTo,   sKing) ;
  900.           CkdDragShow    (hps, pptlTo,   sColor, sKing) ;
  901.  
  902.           return ;
  903.           }
  904.  
  905.      ptlCenter.x = min (pptlFrom->x, pptlTo->x) ;
  906.      ptlCenter.y = min (pptlFrom->y, pptlTo->y) ;
  907.      CkdPieceOriginFromCenterDevice (&ptlOrigin, &ptlCenter) ;
  908.  
  909.                // Copy screen into ahbmMove bitmap in hpsMemory2
  910.  
  911.      aptl[0].x = 0 ;
  912.      aptl[0].y = 0 ;
  913.      aptl[1].x = sizlMove[sKing].cx ;
  914.      aptl[1].y = sizlMove[sKing].cy ;
  915.      aptl[2]   = ptlOrigin ;
  916.  
  917.      GpiSetBitmap (hpsMemory2, ahbmMove[sKing]) ;
  918.      GpiBitBlt (hpsMemory2, hps, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE) ;
  919.  
  920.                // Do restore, save, & show to hpsMemory2
  921.  
  922.      ptlFrom.x = pptlFrom->x - ptlOrigin.x ;
  923.      ptlFrom.y = pptlFrom->y - ptlOrigin.y ;
  924.      ptlTo.x   = pptlTo->x   - ptlOrigin.x ;
  925.      ptlTo.y   = pptlTo->y   - ptlOrigin.y ;
  926.  
  927.      CkdDragRestore (hpsMemory2, &ptlFrom, sKing) ;
  928.      CkdDragSave    (hpsMemory2, &ptlTo,   sKing) ;
  929.      CkdDragShow    (hpsMemory2, &ptlTo,   sColor, sKing) ;
  930.  
  931.                // Copy ahbmMove bitmap in hpsMemory2 to screen
  932.  
  933.      aptl[0]   = ptlOrigin ;
  934.      aptl[1].x = ptlOrigin.x + sizlMove[sKing].cx ;
  935.      aptl[1].y = ptlOrigin.y + sizlMove[sKing].cy ;
  936.      aptl[2].x = 0 ;
  937.      aptl[2].y = 0 ;
  938.  
  939.      GpiBitBlt (hps, hpsMemory2, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE) ;
  940.      GpiSetBitmap (hpsMemory2, NULL) ;
  941.      }
  942.  
  943.      /*-----------------------------------------------
  944.         CkdDragDeposit: Displays piece at end of drag
  945.        -----------------------------------------------*/
  946.  
  947. VOID CkdDragDeposit (HPS hps, SHORT x, SHORT y, SHORT sColor, SHORT sKing)
  948.      {
  949.      POINTL ptlOrigin ;
  950.  
  951.      CkdQuerySquarePieceOrigin (x, y, &ptlOrigin) ;
  952.      GpiConvert (hps, CVTC_PAGE, CVTC_DEVICE, 1L, &ptlOrigin) ;
  953.      CkdShowPiece (hps, &ptlOrigin, sColor, sKing) ;
  954.      }
  955.  
  956.      /*----------------------------------------------------
  957.         CkdQueryNearestXYFromPoint: For keyboard interface
  958.        ----------------------------------------------------*/
  959.  
  960. VOID CkdQueryNearestXYFromPoint (HPS hps, POINTL *pptlMouse, SHORT *px,
  961.                                                              SHORT *py)
  962.      {
  963.      POINTL ptl, aptlSquare[4] ;
  964.      SHORT  x, y ;
  965.  
  966.      ptl = *pptlMouse ;
  967.      GpiConvert (hps, CVTC_DEVICE, CVTC_PAGE, 1L, &ptl) ;
  968.  
  969.      for (y = 0 ; y < 7 ; y++)
  970.           {
  971.           CkdQuerySquareCoords (0, y, aptlSquare) ;
  972.           if (aptlSquare[3].y > ptl.y)
  973.                break ;
  974.           }
  975.  
  976.      for (x = 0 ; x < 7 ; x++)
  977.           {
  978.           CkdQuerySquareCoords (x, y, aptlSquare) ;
  979.           if ((aptlSquare[0].x + aptlSquare[1].x) / 2 > ptl.x)
  980.                break ;
  981.           }
  982.      *px = x ;
  983.      *py = y ;
  984.      }
  985.  
  986.      /*----------------------------------------------------
  987.         CkdSlightOffsetFromXY: For keyboard interface
  988.        ----------------------------------------------------*/
  989.  
  990. VOID CkdQuerySlightOffsetFromXY (HPS hps, SHORT x, SHORT y, POINTL *pptl)
  991.      {
  992.      POINTL ptlCenter, ptlOrigin ;
  993.  
  994.      CkdQuerySquareCenter (x, y, &ptlCenter) ;
  995.      CkdQuerySquareOrigin (x, y, &ptlOrigin) ;
  996.  
  997.      pptl->x = (3 * ptlCenter.x + ptlOrigin.x) / 4 ;
  998.      pptl->y = (3 * ptlCenter.y + ptlOrigin.y) / 4 ;
  999.  
  1000.      GpiConvert (hps, CVTC_PAGE, CVTC_DEVICE, 1L, pptl) ;
  1001.      }
  1002.